home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
CMDPARSE.C
< prev
next >
Wrap
Text File
|
1993-08-09
|
7KB
|
333 lines
/* Parse command line, set up command arguments Unix-style, and call function.
* Note: argument is modified (delimiters are overwritten with nulls)
* Improved error handling by Brian Boesch of Stanford University
*/
#include <stdio.h>
#include <ctype.h>
#include "global.h"
#include "config.h"
#include "proc.h"
#include "cmdparse.h"
static char * near
stringparse(char *line)
{
char num, *cp = line;
while(*line != '\0' && *line != '\"') {
if(*line == '\\') {
line++;
switch ( *line++ ) {
case 'n':
*cp++ = '\n';
break;
case 't':
*cp++ = '\t';
break;
case 'v':
*cp++ = '\v';
break;
case 'b':
*cp++ = '\b';
break;
case 'r':
*cp++ = '\r';
break;
case 'f':
*cp++ = '\f';
break;
case 'a':
*cp++ = '\a';
break;
case '\\':
*cp++ = '\\';
break;
case '\?':
*cp++ = '\?';
break;
case '\'':
*cp++ = '\'';
break;
case '\"':
*cp++ = '\"';
break;
case 'x':
num = strtoul( --line, &line, 16 );
*cp++ = num;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
num = strtoul( --line, &line, 8 );
*cp++ = num;
break;
case '\0':
return NULLCHAR;
default:
*cp++ = *(line - 1);
break;
};
} else {
*cp++ = *line++;
}
}
if(*line == '\"')
line++; /* skip final quote */
*cp = '\0'; /* terminate string */
return line;
}
int
cmdparse(struct cmds cmds[],char *line,void *p)
{
struct cmds *cmdp;
char *argv[NARG], *cp;
int argc, i;
/* Remove cr/lf */
rip(line);
for(argc = 0; argc < NARG; argc++)
argv[argc] = NULLCHAR;
for(argc = 0; argc < NARG; ) {
int qflag = FALSE;
/* Skip leading white space */
while(*line == ' ' || *line == '\t')
line++;
if(*line == '\0')
break;
/* Check for quoted token */
if(*line == '"'){
line++; /* Suppress quote */
qflag = TRUE;
}
argv[argc++] = line; /* Beginning of token */
if(qflag){
/* Find terminating delimiter */
if((line = stringparse(line)) == NULLCHAR){
return -1;
}
} else {
/* Find space or tab. If not present,
* then we've already found the last
* token.
*/
if((cp = strpbrk(line," \t")) == NULL)
break;
*cp++ = '\0';
line = cp;
}
}
if(argc < 1) { /* empty command line */
argc = 1;
argv[0] = "";
}
/* Lines beginning with "#" are comments */
if(argv[0] == NULLCHAR || argv[0][0] == '#')
return 0;
/* Look up command in table; prefix matches are OK */
for(cmdp = cmds; cmdp->name != NULLCHAR; cmdp++){
if(strncmp(*argv,cmdp->name,strlen(*argv)) == 0)
break;
}
if(cmdp->name == NULLCHAR) {
if(cmdp->argc_errmsg != NULLCHAR)
tprintf("%s\n",cmdp->argc_errmsg);
return -1;
} else {
if(argc < cmdp->argcmin) {
/* Insufficient arguments */
tprintf("Usage: %s\n",cmdp->argc_errmsg);
return -1;
} else {
if(cmdp->stksize == 0){
return (*cmdp->func)(argc,argv,p);
} else {
/* Make private copy of argv and args,
* spawn off subprocess and return.
*/
char **pargv = cxallocw(argc,sizeof(char *));
for(i = 0; i < argc; i++) {
pargv[i] = strxdup(argv[i]);
}
newproc(cmdp->name,cmdp->stksize,
(void (*)())cmdp->func,argc,pargv,p,1);
return(0);
}
}
}
}
/* Call a subcommand based on the first token in an already-parsed line */
int
subcmd(struct cmds tab[],int argc,char **argv,void *p)
{
struct cmds *cmdp;
int i, found = 0;
/* Strip off first token and pass rest of line to subcommand */
if(argc < 1) {
tputs("SUBCMD - Don't know what to do\n");
return -1;
}
if(argc > 1) {
argc--;
argv++;
for(cmdp = tab; cmdp->name != NULLCHAR; cmdp++) {
if(strncmp(*argv,cmdp->name,strlen(*argv)) == 0){
found = 1;
break;
}
}
}
if(!found) {
tputs("available subcommands:\n");
for(i = 0, cmdp = tab; cmdp->name != NULLCHAR; cmdp++, i = (i+1)%5)
tprintf("%-15.15s%s",cmdp->name,(i == 4) ? "\n" : "");
if(i)
tputs("\n");
return -1;
}
if(argc < cmdp->argcmin){
if(cmdp->argc_errmsg != NULLCHAR)
tprintf("Usage: %s\n",cmdp->argc_errmsg);
return -1;
}
if(cmdp->stksize == 0){
return (*cmdp->func)(argc,argv,p);
} else {
/* Make private copy of argv and args */
char **pargv = cxallocw(argc,sizeof(char *));
for(i = 0; i < argc; i++) {
pargv[i] = strxdup(argv[i]);
}
newproc(cmdp->name,cmdp->stksize,
(void (*)())cmdp->func,argc,pargv,p,1);
return(0);
}
}
/* Subroutine for setting and displaying boolean flags */
int
setbool(int *var,char *label,int argc,char **argv)
{
static struct boolcmd {
char *str; /* Token */
int val; /* Value */
} Boolcmds[] = {
"yes", TRUE, /* Synonyms for "true" */
"true", TRUE,
"on", TRUE,
"1", TRUE,
"set", TRUE,
"enable", TRUE,
"no", FALSE, /* Synonyms for "false" */
"false", FALSE,
"off", FALSE,
"0", FALSE,
"clear", FALSE,
"disable", FALSE,
NULLCHAR
};
struct boolcmd *bc;
if(argc < 2){
tprintf("%s: %s\n",label,*var ? "on" : "off");
return 0;
}
for(bc = Boolcmds; bc->str != NULLCHAR; bc++) {
if(strnicmp(argv[1],bc->str,strlen(argv[1])) == 0) {
*var = bc->val;
return 0;
}
}
tputs("Valid options:");
for(bc = Boolcmds; bc->str != NULLCHAR; bc++) {
tprintf(" %s",bc->str);
}
tputs("\n");
return 1;
}
/* Subroutine for setting and displaying long variables */
int
setlong(long *var,char *label,int argc,char **argv)
{
if(argc < 2) {
tprintf("%s: %ld\n",label,*var);
} else {
*var = atol(argv[1]);
}
return 0;
}
/* Subroutine for setting and displaying short variables */
int
setshort(unsigned short *var,char *label,int argc,char **argv)
{
if(argc < 2) {
tprintf("%s: %u\n",label,*var);
} else {
*var = atoi(argv[1]);
}
return 0;
}
/* Subroutine for setting and displaying integer variables */
int
setint(int *var,char *label,int argc,char **argv)
{
if(argc < 2) {
tprintf("%s: %u\n",label,*var);
} else {
*var = atoi(argv[1]);
}
return 0;
}
/* Subroutine for setting and displaying int variables (with range check) */
int
setintrc(int16 *var,char *label,int argc,char **argv,int minval,int16 maxval)
{
if (argc < 2) {
tprintf("%s: %u\n", label, *var);
} else {
int16 tmp = atol(argv[1]);
if(isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
tprintf("%s must be %i..%i\n", label, minval, maxval);
return -1;
}
*var = tmp;
}
return 0;
}
#ifdef MODEM
/* Subroutine for setting and displaying unsigned integer variables */
int
setuns(unsigned *var,char *label,int argc,char **argv)
{
if(argc < 2) {
tprintf("%s: %u\n",label,*var);
} else {
*var = (unsigned)atoi(argv[1]);
}
return 0;
}
#endif